﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PHMEE
{
    public class RedisHelper
    {
        private readonly IDatabase _db;
        public RedisHelper(string configuration)
        {
            var connection = ConnectionMultiplexer.Connect(configuration);
            _db = connection.GetDatabase();
        }
        #region String 数据类型
        /// <summary>
        /// 添加或更新指定的字符串值
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="value">需要存储的值</param>
        /// <param name="expiration">可选的过期时间</param>
        /// <returns></returns>
        public async Task SetStringAsync(string key, string value, TimeSpan? expiration = null)
        {
            // 如果提供了过期时间，则设置该键的生存时间
            await _db.StringSetAsync(key, value, expiration);
        }
        /// <summary>
        /// 获取指定键的字符串值
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <returns>返回对应的值，如果键不存在则返回null</returns>
        public async Task<string> GetStringAsync(string key)
        {
            return await _db.StringGetAsync(key);
        }
        /// <summary>
        /// 删除指定的键
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <returns>如果删除成功返回true，否则返回false</returns>
        public async Task<bool> DeleteStringAsync(string key)
        {
            return await _db.KeyDeleteAsync(key);
        }

        /// <summary>
        /// 判断指定的键是否存在
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <returns>如果键存在返回true，否则返回false</returns>
        public async Task<bool> KeyExistsAsync(string key)
        {
            return await _db.KeyExistsAsync(key);
        }
        #endregion

        #region Set 数据类型
        /// <summary>
        /// Set集合中添加元素
        /// </summary>
        /// <param name="key">Set的键</param>
        /// <param name="value">需要添加的元素</param>
        /// <param name="expiration">可选的过期时间，应用于整个Set键</param>
        /// <returns>返回是否成功添加</returns>
        public async Task<bool> SetAddAsync(string key, string value, TimeSpan? expiration = null)
        {
            bool isAdded = await _db.SetAddAsync(key, value);
            // 如果设置了过期时间，则为整个Set键设置过期时间
            if (expiration.HasValue)
            {
                await _db.KeyExpireAsync(key, expiration);
            }

            return isAdded;
        }

        /// <summary>
        /// 从Set集合中移除一个元素
        /// </summary>
        /// <param name="key">Set的键</param>
        /// <param name="value">需要移除的元素</param>
        /// <returns>返回是否成功移除</returns>
        public async Task<bool> SetRemoveAsync(string key, string value)
        {
            return await _db.SetRemoveAsync(key, value);
        }

        /// <summary>
        /// 检查Set集合中是否包含某个元素
        /// </summary>
        /// <param name="key">Set的键</param>
        /// <param name="value">要检查的元素</param>
        /// <returns>如果包含该元素返回true，否则返回false</returns>
        public async Task<bool> SetContainsAsync(string key, string value)
        {
            return await _db.SetContainsAsync(key, value);
        }

        /// <summary>
        /// 获取Set集合中的所有元素
        /// </summary>
        /// <param name="key">Set的键</param>
        /// <returns>返回集合中的所有元素</returns>
        public async Task<HashSet<string>> GetAllSetMembersAsync(string key)
        {
            var members = await _db.SetMembersAsync(key);
            var result = new HashSet<string>();
            foreach (var member in members)
            {
                result.Add(member.ToString());
            }
            return result;
        }
        /// <summary>
        /// 获取Set集合中的元素数量
        /// </summary>
        /// <param name="key">Set的键</param>
        /// <returns>返回集合中元素的数量</returns>
        public async Task<long> GetSetLengthAsync(string key)
        {
            return await _db.SetLengthAsync(key);
        }
        #endregion

        #region Hash 数据类型
        /// <summary>
        /// 为指定的键和字段设置哈希值
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <param name="value">需要存储的值</param>
        /// <returns></returns>
        public async Task HashSetAsync(string key, string field, string value, TimeSpan? expiration = null)
        {
            await _db.HashSetAsync(key, field, value);
            // 如果有过期时间，为整个哈希键设置过期时间
            if (expiration.HasValue)
            {
                await _db.KeyExpireAsync(key, expiration.Value);
            }
        }
        /// <summary>
        /// 为指定的键和字段设置哈希值--同步
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <param name="value">需要存储的值</param>
        /// <returns></returns>
        public void HashSet(string key, string field, string value, TimeSpan? expiration = null)
        {
            _db.HashSet(key, field, value);

            // 如果有过期时间，为整个哈希键设置过期时间
            if (expiration.HasValue)
            {
                _db.KeyExpireAsync(key, expiration.Value);
            }
        }
        /// <summary>
        /// 获取哈希中指定字段的值
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <returns>返回对应的值，如果字段不存在则返回null</returns>
        public async Task<string> HashGetAsync(string key, string field)
        {
            return await _db.HashGetAsync(key, field);
        }
        /// <summary>
        /// 获取哈希中指定字段的值--同步
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <returns>返回对应的值，如果字段不存在则返回null</returns>
        public string HashGet(string key, string field)
        {
            return _db.HashGet(key, field);
        }
        /// <summary>
        /// 删除哈希中的指定字段
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <returns>返回是否成功删除</returns>
        public async Task<bool> HashDeleteAsync(string key, string field)
        {
            return await _db.HashDeleteAsync(key, field);
        }
        // <summary>
        /// 删除整个哈希键
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <returns>如果删除成功返回true，否则返回false</returns>
        public async Task<bool> DeleteHashAsync(string key)
        {
            return await _db.KeyDeleteAsync(key);
        }
        /// <summary>
        /// 获取哈希中的所有字段和值
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <returns>返回包含所有字段和值的字典</returns>
        public async Task<Dictionary<string, string>> HashGetAllAsync(string key)
        {
            var hashEntries = await _db.HashGetAllAsync(key);
            return hashEntries.ToDictionary(
                entry => entry.Name.ToString(),
                entry => entry.Value.ToString()
            );
        }

        /// <summary>
        /// 检查哈希中是否存在指定字段
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <returns>如果存在返回true，否则返回false</returns>
        public async Task<bool> HashExistsAsync(string key, string field)
        {
            return await _db.HashExistsAsync(key, field);
        }

        /// <summary>
        /// 获取哈希中的字段数量
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <returns>返回哈希中的字段数量</returns>
        public async Task<long> HashLengthAsync(string key)
        {
            return await _db.HashLengthAsync(key);
        }

        /// <summary>
        /// 为哈希中的字段值加上指定的增量值（适用于数值类型）
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <param name="increment">增量值</param>
        /// <returns>返回加上增量后的新值</returns>
        public async Task<long> HashIncrementAsync(string key, string field, long increment)
        {
            return await _db.HashIncrementAsync(key, field, increment);
        }

        /// <summary>
        /// 为哈希中的字段值减少指定的值（适用于数值类型）
        /// </summary>
        /// <param name="key">Redis键</param>
        /// <param name="field">哈希字段</param>
        /// <param name="decrement">减少值</param>
        /// <returns>返回减少后的新值</returns>
        public async Task<long> HashDecrementAsync(string key, string field, long decrement)
        {
            return await _db.HashDecrementAsync(key, field, decrement);
        }
        #endregion
    }
}
